﻿#include "dataAnalysisThread.h"
#include <QDebug>
#include <mainwindow.h>

using namespace std;
DataAnalysisThread::DataAnalysisThread(QObject *parent): QObject{parent}
{
    analyseClient = new Analyse();
    derivedata1 = new derivedata();
    this->moveToThread(&thread);
    thread.start();
}

void DataAnalysisThread::run()
{
    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);

    QString sql="Select CycleNum From AmplStepTemp where ProgramId=(Select AmplGuid from ExperimentInfo) and IsCollect='是'";
    query.exec(sql);

    while (query.next()) {
        analyseClient->leh=query.value("CycleNum").toInt();
    }
//    bjpc();// 背景偏差值

    db.transaction();

    sql="DELETE FROM FluorescenceData WHERE rowid NOT IN (SELECT MIN(rowid) FROM FluorescenceData GROUP BY positionNumber, CyclesNumber)";
    query.exec(sql);

    sql=QString("Delete from FluorescenceLvData");
    query.exec(sql);

    sql=QString("Delete from FluorescenceLvboData");
    query.exec(sql);

    sql=QString("Delete from FluorescenceLogData");
    query.exec(sql);

    sql=QString("Delete from FluorescenceNormalData");
    query.exec(sql);

    sql=QString("Delete from FluorescenceLvboTempTable");
    query.exec(sql);

    sql=QString("Delete from FluorescenceTempTable");
    query.exec(sql);

    sql=QString("Delete from FluorescenceNormalTempTable");
    query.exec(sql);

    sql=QString("Delete from FluorescenceLogTempTable");
    query.exec(sql);

    sql=QString("Delete from FluorescenceResultTable");
    query.exec(sql);

    sql=QString("Insert into FluorescenceNormalData Select * from FluorescenceData");
    query.exec(sql);

    sql=QString("Insert into FluorescenceLvData Select * from FluorescenceData");
    query.exec(sql);

    sql=QString("Insert into FluorescenceLvboData Select * from FluorescenceData");
    query.exec(sql);

    sql=QString("Insert into FluorescenceLogData Select * from FluorescenceData");
    query.exec(sql);

    db.commit();

    for(int i=1;i<=96;i++){
        QVector<int> fData;
        QVector<int> rData;
        QVector<int> cData;
        QVector<int> vData;
        QString  sql=QString("select f.sampleId,FAM,ROX,CY5,VIC "
                             "From FluorescenceData f "
                             "where PositionNumber='%1' "
                             "order by CyclesNumber;").arg(QString::number(i));
        query.exec(sql);

        QVector<int> data;
        QString sampleId;
        while (query.next()) {
            sampleId=query.value("SampleId").toString();
            fData.append(query.value("FAM").toInt());
            rData.append(query.value("ROX").toInt());
            cData.append(query.value("CY5").toInt());
            vData.append(query.value("VIC").toInt());
        }

        if(!sampleId.isEmpty()){
            analyseAndSaveData(fData,sampleId,"FAM");
            analyseAndSaveData(rData,sampleId,"ROX");
            analyseAndSaveData(cData,sampleId,"CY5");
            analyseAndSaveData(vData,sampleId,"VIC");
        }
    }

    db.transaction();
    sql="Update FluorescenceNormalData set "
        "FAM=(Select AccessVal from FluorescenceNormalTempTable where FluorescenceNormalData.SampleId=FluorescenceNormalTempTable.SampleID and FluorescenceNormalData.CyclesNumber=FluorescenceNormalTempTable.CyclesNumber and FluorescenceNormalTempTable.AccessType='FAM'),"
        "VIC=(Select AccessVal from FluorescenceNormalTempTable where FluorescenceNormalData.SampleId=FluorescenceNormalTempTable.SampleID and FluorescenceNormalData.CyclesNumber=FluorescenceNormalTempTable.CyclesNumber and FluorescenceNormalTempTable.AccessType='VIC'),"
        "ROX=(Select AccessVal from FluorescenceNormalTempTable where FluorescenceNormalData.SampleId=FluorescenceNormalTempTable.SampleID and FluorescenceNormalData.CyclesNumber=FluorescenceNormalTempTable.CyclesNumber and FluorescenceNormalTempTable.AccessType='ROX'),"
        "CY5=(Select AccessVal from FluorescenceNormalTempTable where FluorescenceNormalData.SampleId=FluorescenceNormalTempTable.SampleID and FluorescenceNormalData.CyclesNumber=FluorescenceNormalTempTable.CyclesNumber and FluorescenceNormalTempTable.AccessType='CY5')";
    query.exec(sql);

    sql="Update FluorescenceLvboData set "
        "FAM=(Select AccessVal from FluorescenceLvboTempTable where FluorescenceLvboData.SampleId=FluorescenceLvboTempTable.SampleID and FluorescenceLvboData.CyclesNumber=FluorescenceLvboTempTable.CyclesNumber and FluorescenceLvboTempTable.AccessType='FAM'),"
        "VIC=(Select AccessVal from FluorescenceLvboTempTable where FluorescenceLvboData.SampleId=FluorescenceLvboTempTable.SampleID and FluorescenceLvboData.CyclesNumber=FluorescenceLvboTempTable.CyclesNumber and FluorescenceLvboTempTable.AccessType='VIC'),"
        "ROX=(Select AccessVal from FluorescenceLvboTempTable where FluorescenceLvboData.SampleId=FluorescenceLvboTempTable.SampleID and FluorescenceLvboData.CyclesNumber=FluorescenceLvboTempTable.CyclesNumber and FluorescenceLvboTempTable.AccessType='ROX'),"
        "CY5=(Select AccessVal from FluorescenceLvboTempTable where FluorescenceLvboData.SampleId=FluorescenceLvboTempTable.SampleID and FluorescenceLvboData.CyclesNumber=FluorescenceLvboTempTable.CyclesNumber and FluorescenceLvboTempTable.AccessType='CY5')";
    query.exec(sql);

    sql="Update FluorescenceLvData set "
        "FAM=(Select AccessVal from FluorescenceTempTable where FluorescenceLvData.SampleId=FluorescenceTempTable.SampleID and FluorescenceLvData.CyclesNumber=FluorescenceTempTable.CyclesNumber and FluorescenceTempTable.AccessType='FAM'),"
        "VIC=(Select AccessVal from FluorescenceTempTable where FluorescenceLvData.SampleId=FluorescenceTempTable.SampleID and FluorescenceLvData.CyclesNumber=FluorescenceTempTable.CyclesNumber and FluorescenceTempTable.AccessType='VIC'),"
        "ROX=(Select AccessVal from FluorescenceTempTable where FluorescenceLvData.SampleId=FluorescenceTempTable.SampleID and FluorescenceLvData.CyclesNumber=FluorescenceTempTable.CyclesNumber and FluorescenceTempTable.AccessType='ROX'),"
        "CY5=(Select AccessVal from FluorescenceTempTable where FluorescenceLvData.SampleId=FluorescenceTempTable.SampleID and FluorescenceLvData.CyclesNumber=FluorescenceTempTable.CyclesNumber and FluorescenceTempTable.AccessType='CY5')";
    query.exec(sql);

    sql="Update FluorescenceLogData set "
        "FAM=(Select AccessVal from FluorescenceLogTempTable where FluorescenceLogData.SampleId=FluorescenceLogTempTable.SampleID and FluorescenceLogData.CyclesNumber=FluorescenceLogTempTable.CyclesNumber and FluorescenceLogTempTable.AccessType='FAM'),"
        "VIC=(Select AccessVal from FluorescenceLogTempTable where FluorescenceLogData.SampleId=FluorescenceLogTempTable.SampleID and FluorescenceLogData.CyclesNumber=FluorescenceLogTempTable.CyclesNumber and FluorescenceLogTempTable.AccessType='VIC'),"
        "ROX=(Select AccessVal from FluorescenceLogTempTable where FluorescenceLogData.SampleId=FluorescenceLogTempTable.SampleID and FluorescenceLogData.CyclesNumber=FluorescenceLogTempTable.CyclesNumber and FluorescenceLogTempTable.AccessType='ROX'),"
        "CY5=(Select AccessVal from FluorescenceLogTempTable where FluorescenceLogData.SampleId=FluorescenceLogTempTable.SampleID and FluorescenceLogData.CyclesNumber=FluorescenceLogTempTable.CyclesNumber and FluorescenceLogTempTable.AccessType='CY5')";
    query.exec(sql);

    sql="update SampleAccessInfo set CtValue=(select case when CTVal>0 then CTVal else 'nan' end from  FluorescenceResultTable f "
        "where SampleAccessInfo.SampleGuid=f.SampleID and "
        "SampleAccessInfo.AccessName= f.AccessType )";
    query.exec(sql);

    db.commit();

    QFile file(MainWindow::experimentSaveDataPath);

    file.open(QFile::WriteOnly|QFile::Text|QIODevice::Append);

    QTextStream out(&file);  //QTextStream会自动将 Unicode 编码同操作系统的编码进行转换

    sql="Select * From FluorescenceData";
    query.exec(sql);
    while (query.next()) {
        QString addSql=QString("Insert into FluorescenceData(SampleId,PositionNumber,CyclesNumber,FAM,VIC,ROX,CY5) Values ('%1','%2','%3','%4','%5','%6','%7')").arg(query.value("SampleId").toString(),query.value("PositionNumber").toString(),
                                                                                                                                                                     query.value("CyclesNumber").toString(),query.value("FAM").toString(),
                                                                                                                                                                     query.value("VIC").toString(),query.value("ROX").toString(),
                                                                                                                                                                     query.value("CY5").toString());
        out<<addSql+"\n";
    }
    sql="Select * From FluorescenceLvData";
    query.exec(sql);
    while (query.next()) {
        QString addSql=QString("Insert into FluorescenceLvData(SampleId,PositionNumber,CyclesNumber,FAM,VIC,ROX,CY5) Values ('%1','%2','%3','%4','%5','%6','%7')").arg(query.value("SampleId").toString(),query.value("PositionNumber").toString(),
                                                                                                                                                                       query.value("CyclesNumber").toString(),query.value("FAM").toString(),
                                                                                                                                                                       query.value("VIC").toString(),query.value("ROX").toString(),
                                                                                                                                                                       query.value("CY5").toString());
        out<<addSql+"\n";
    }
    sql="Select * From FluorescenceLvBoData";
    query.exec(sql);
    while (query.next()) {
        QString addSql=QString("Insert into FluorescenceLvBoData(SampleId,PositionNumber,CyclesNumber,FAM,VIC,ROX,CY5) Values ('%1','%2','%3','%4','%5','%6','%7')").arg(query.value("SampleId").toString(),query.value("PositionNumber").toString(),
                                                                                                                                                                         query.value("CyclesNumber").toString(),query.value("FAM").toString(),
                                                                                                                                                                         query.value("VIC").toString(),query.value("ROX").toString(),
                                                                                                                                                                         query.value("CY5").toString());
        out<<addSql+"\n";
    }
    sql="Select * From FluorescenceNormalData";
    query.exec(sql);
    while (query.next()) {
        QString addSql=QString("Insert into FluorescenceNormalData(SampleId,PositionNumber,CyclesNumber,FAM,VIC,ROX,CY5) Values ('%1','%2','%3','%4','%5','%6','%7')").arg(query.value("SampleId").toString(),query.value("PositionNumber").toString(),
                                                                                                                                                                           query.value("CyclesNumber").toString(),query.value("FAM").toString(),
                                                                                                                                                                           query.value("VIC").toString(),query.value("ROX").toString(),
                                                                                                                                                                           query.value("CY5").toString());
        out<<addSql+"\n";
    }

    sql="Select * From FluorescenceLogData";
    query.exec(sql);
    while (query.next()) {
        QString addSql=QString("Insert into FluorescenceLogData(SampleId,PositionNumber,CyclesNumber,FAM,VIC,ROX,CY5) Values ('%1','%2','%3','%4','%5','%6','%7')").arg(query.value("SampleId").toString(),query.value("PositionNumber").toString(),
                                                                                                                                                                        query.value("CyclesNumber").toString(),query.value("FAM").toString(),
                                                                                                                                                                        query.value("VIC").toString(),query.value("ROX").toString(),
                                                                                                                                                                        query.value("CY5").toString());
        out<<addSql+"\n";
    }

    sql="Select * From FluorescenceResultTable";
    query.exec(sql);
    while (query.next()) {
        QString addSql=QString("Insert into FluorescenceResultTable Values ('%1','%2','%3','%4','%5','%6','%7','%8')").arg(query.value("SampleID").toString(),query.value("AccessType").toString(),
                                                                                                                           query.value("BaselineValue").toString(),query.value("Threshold").toString(),
                                                                                                                           query.value("Efficiency").toString(),query.value("Slope").toString(),
                                                                                                                           query.value("CTVal").toString(),query.value("StandardDeviation").toString());
        out<<addSql+"\n";
    }
    sql="update SampleAccessInfo set CtValue=(select case when CTVal>0 then CTVal else 'nan' end from  FluorescenceResultTable f "
        "where SampleAccessInfo.SampleGuid=f.SampleID and "
        "SampleAccessInfo.AccessName= f.AccessType )";
    out<<sql + "\n" ;

    file.close();

#ifdef Q_OS_ANDROID
//    FtpHelpers *ftp=new FtpHelpers();
//    ftp->uploadFile(MainWindow::experimentSaveDataPath);
#endif
    derivedata1 = new derivedata();
    derivedata1->refOriginalCurveTable();
    derivedata1->refAmplificationCurveTable();
    derivedata1->standardCurveChart();
    derivedata1->guide();
    derivedata1->datao();
    thread.quit();
}

//计算并保存数据
void DataAnalysisThread::analyseAndSaveData( QVector<int> ying,QString sampleId,QString accessType){
    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);
    double yuan[100];

    db.transaction();

    std::vector<int> stdVector = std::vector<int>(ying.begin(),ying.end());
    int* array = new int[stdVector.size()];
    for (size_t i = 0; i < stdVector.size(); ++i){
        array[i] = stdVector[i];
        yuan[i] = stdVector[i];
    }
    analyseClient->p=array;

    //    double Flb[100];
    //    analyseClient->yingBase(Flb);

    double Flc[100];

    double pop[5][5] = {{0.986,0.057,-0.086,0.057,-0.014},
                        {0.057,0.771,0.343,-0.228,0.057},
                        {-0.086,0.343,0.486,0.343,-0.086},
                        {0.057,-0.229,0.343,0.771,0.057},
                        {-0.014,0.057,-0.086,0.057,0.986}};
    analyseClient->IIR_Init(Flc,yuan,pop);

    for(int i=0;i<analyseClient->leh;i++){
        QString sql=QString("Insert Into FluorescenceLvboTempTable values('%1','%2','%3','%4')").arg(sampleId,QString::number(i+1),accessType,QString::number(Flc[i]));
        query.exec(sql);
    }
    analyseClient->maxLvbo = Flc[0];
    for(int i=0;i< analyseClient->leh ;i++)
    {
        if(Flc[i]>=analyseClient->maxLvbo)
        {
            analyseClient->maxLvbo = Flc[i];
        }
    }

    double E,K,S,maxF,Ct;
    double Fa[100],Fb[100], Fc[100];

    E=analyseClient->K_slope(Flc,Fa,analyseClient->leh,5);
    K = analyseClient->yingK(E);

    maxF=analyseClient->yingFDM(Flc,Fc);
    //    maxF=Fc[0];
    for(int i=0;i< analyseClient->leh-1;i++){
        if(Fc[i]>=maxF){
            maxF=Fc[i];
            analyseClient->c0=i+1;
        }
    }

    double SDM[100];
    double Fn[100];

    analyseClient->yingSDM(Fc,SDM);
    S = analyseClient->xunhuanS(Flc,3,15);

    double maxLvbo=0;
    double yingAvg=0;
    double num=0;
    for(int i=0;i<analyseClient->leh;i++){
        if(maxLvbo<Flc[i]){
            maxLvbo=Flc[i];
        }
        if(analyseClient->c0-1==0){
            if(i>=2&&i<15){
                yingAvg+=Flc[i];
                num++;
            }
        }else{
            if(i>=2&&i<analyseClient->c0-1){
                yingAvg+=Flc[i];
                num++;
            }
        }
    }
    analyseClient->yingJAvg=yingAvg/num;

    analyseClient->sigmodDelta(maxLvbo,Flc,K,Fn,1);

    for(int i=0;i<analyseClient->leh;i++){
        QString sql=QString("Insert Into FluorescenceTempTable values('%1','%2','%3','%4')").arg(sampleId,QString::number(i+1),accessType,QString::number(Fn[i]));
        query.exec(sql);
    }

    //计算基线值
    QString baseLineVal= QString::number(analyseClient->yingJAvg,'f',4);
    for(int i=0;i< analyseClient->leh;i++)
    {
        Fa[i] = analyseClient->yingJAvg;
    }

    E = analyseClient->eff(Fn,Fa,analyseClient->leh,5); //根据拟合数据重新计算效率和斜率
    QString Efficiency= QString::number(E,'f',4);
    K = analyseClient->yingK(E) ;
    QString Slope= QString::number(K,'f',4);//显示斜率
    for(int i=0;i<analyseClient->leh;i++)
    {
        Fb[i] =S;
    }

    QString Threshold= QString::number(S,'f',4);

    Ct = analyseClient->yingCTJiao(Fn,S,15); //计算CT值根据拟合后数据曲线
    QString StandardDeviation= QString::number(analyseClient->std,'f',4);

    QString sql=QString("Insert into FluorescenceResultTable values('%1','%2','%3','%4',"
                        "'%5','%6','%7','%8')").arg( sampleId,accessType,baseLineVal,Threshold,Efficiency,Slope,
                                                     QString::number(Ct,'f',2),StandardDeviation);
    query.exec(sql);

    double normalizeN[100];

    analyseClient->normalizeN(Fn,normalizeN);

    for(int i=0;i<analyseClient->leh;i++){
        QString sql=QString("Insert Into FluorescenceNormalTempTable values('%1','%2','%3','%4')").arg(sampleId,QString::number(i+1),accessType,QString::number(normalizeN[i]));
        query.exec(sql);
    }
    db.commit();

    double logarithmN[100];
    for(int i=0;i<analyseClient->leh;i++){
        Fn[i]=Fn[i]+baseLineVal.toDouble();
    }
    analyseClient->logarithm(Fn,logarithmN);
    for(int i=0;i<analyseClient->leh;i++){
        QString sql=QString("Insert Into FluorescenceLogTempTable values('%1','%2','%3','%4')").arg(sampleId,QString::number(i+1),accessType,QString::number(logarithmN[i]));
        query.exec(sql);
    }

    db.commit();
}

QString DataAnalysisThread::GetDateString(int val){
    return QString::number(val).length()==2?QString::number(val): "0"+QString::number(val);
}
